Basics
AppleScript is a scripting language. Scripting languages have all the capabilities
of other programming languages, but are easier to use because their structure
is closer to everyday English.
AppleScripts can store data for later use and examine their surroundings to
determine what to do next. They can also loop through certain instructions,
repeating them as many times as you like, or until something specific happens.
These features, and others, are what makes a scripting language - particularly
AppleScript ideal for anyone that wants to automate a task.
AppleScript is different from other scripting languages because its reach isn't
limited to a single application. AppleScript is part of the Macintosh operating
system, and that enables it to work with several different applications at once
if necessary. You can extract data from one application and hand it to another
for processing with AppleScript, and it can even be used to control other Macs
over the network.
How to start
You can write simple command aliases in AppleScript, but the real power comes
when you use "event handlers". These are snippets of AppleScript that
you write and load into Snak. Snak will then call your event handlers when particular
events happen, like someone joining a channel, leaving a channel, saying something,
sending you a private message and more. The event handlers lets you truly customize
the way Snak works and responds to events.
There are many good books about AppleScript, and I can in particular recommend
"The TAO of AppleScript" by Derrick Schneider and "AppleScript
Language Guide" from Apple that you can order from the print on demand
service at http://www.fatbrain.com
In order to write an AppleScript that uses Snak, you need to open the Script
Editor application that was installed as part of your operating system. In recent
system versions it will be in the folder "Apple Extras:AppleScript"
A key idea in AppleScript is that every scriptable application contains a dictionary
of the commands and elements it knows about. To see the Snak dictionary, run
the Script Editor and select "Open Dictionary" under the file menu
and select the Snak application:
Under the heading "Snak Suite" you see all the commands you can send
to Snak -
connect/disconnect/echo/do/type/select/match
and all the internal elements of the application that you can access through
an AppleScript -
channels, connections, users, ignoreitems ... and many more.
Your first script
First, launch the Script Editor application. This is where you will write the
text of the script.
This is an example of a simple, yet (somewhat) useful little script. Once it
is loaded into snak you will be able to type "/countops" and have
the script execute and tell you the ratio of channel operators to normal users.
The script asks Snak how many users are in the current channel, and how many
ops there are among them. Then it calculates the ratio and displays a message.
Type the following text and save the file into the Scripts folder that is in
the Snak folder. Save it under the filename "countops" (no spaces).
Don't worry that you might not understand all of it. The rest of this chapter
will attempt to explain what is going on.
on run
tell application "Snak 4.7" set n to numberofusers of channel currentchannel of connection currentconnection
set ops to count (get (every user whose op = true) of channel currentchannel of
connection currentconnection)
set percent to ops / n * 100 as text
set percent to (round (percent + 0.5))
set commandstring to "/me sees " & ops & " gods and "
& n - ops & " mortals on " & currentchannel & ".
" & percent & "% of the people in " & currentchannel & " are gods." do commandstring
end tellend run
There are five main parts to AppleScript:
Objects - which points to items and information inside the application
Commands - which acts on those items and information
Variables - which allows you to store data for later use
Conditionals - which enable your script to make decisions based on a set of conditions
Repeat loops - which give you the capability to execute commands repeatedly
The above script shows examples of objects, commands, conditionals and variables.
Starting with the first line "on run" this is a line that tells Snak
in what situation to run the snippet, namely when the uses types "/countops".
Other situations are explained later when event handlers are introduced.
The "tell application "Snak 4.6"" line is used by the AppleScript
system itself and is used to set the target for the following block of AppleScript.
Notice how the Script Editor automatically indents the following block.
Now we get to the core of the little script, the place where the interesting action
takes place. The next line uses both objects and a variable.
"set n to numberofusers of channel currentchannel of connection currentconnection"
Here we ask Snak a complex question - how many users are there in the current
channel on the current connection, and we store the result into a variable called
"n". The channel and the connection are examples of objects.
A central concept in understanding AppleScript is that most scriptable applications
have an "object hierarchy" meaning that objects are nested inside each
other. You ask the top object (the application) for an object (the connection)
that contains your ultimate goal (the channel), and then you ask that channel
object for specific information like the number of users.
The "tell application "Snak 4.6"" line you saw first points
out the top object (the application) and the "set n to ..." line will
first ask for the connection from the application, and then ask for the channel
from the connection, and then it asks the channel for the number of users. Try
and read the line from the right and you will see the sequence.
Trust me, once you understand the idea it really makes sense :-)
Snaks object hierarchy is:
The application contains connections (and more)
A connection contains channels (and more)
A channel contains users (and more)
The following line is quite complex.
"set ops to count (get (every user whose op = true) of channel currentchannel
of connection currentconnection)"
Like the previous one it uses a variable and objects, but it also introduces a
conditional operation. Again we find a channel object but this time we ask it
for a list of all users in the channel whose "op" status is true, meaning
that they are channel operators. Then we take the number of results and store
in a variable.
The "whose" conditional allows you to easily gather a collection of
objects that satisfy a condition.
The next few lines perform the ratio calculation, and put together the string
of text that Snak should display with the result.
"set commandstring to "/me sees .."
This line looks difficult, but all it does is to pull together the information
we've already found, and fill out a variable that holds a line of text. You may
recognize "/me" as a Snak command, but this line just puts together
a line of text that starts with the "/me" command. The line is stored
in a variable called "commandstring".
"do commandstring"
Finally we get to do an actual AppleScript command. We have a potential point
of confusion here because we are mixing two different kinds of commands. There
are normal Snak commands like you type in at the command line like "/me",
and then there are Snak AppleScript commands like "do". The "do"
Snak AppleScript command makes Snak execute a normal command as if you typed it
in through the command line.
That means that you have access to all the built in Snak commands as well as any
commands you define in the existing ircII language, from within an AppleScript.
So the "do commandstring" line simply executes the "/me sees ..."
command as if you had typed it in yourself, which result in the ratio of ops to
normal users being written out and sent as an action message to the channel.
How to load and run AppleScripts
In order to use an AppleScript it needs to be loaded into Snak. Type "/load
scriptname" to make Snak read in and prepare the script to be run. If you
have a handler in the script called "on load" it will be called right
away. Snak will also look for a handler called "on idle" and start executing
it if it is present.
If you type the name of the script as a command, the "on run" handler
in the script will be run. At this time it is not possible to pass parameters
to an AppleScript command, so you are encouraged to use the ircII language to
write command aliases. This shortcoming will be remedied.
During development of an AppleScript it is frequently useful to unload an existing
script in order to modify it and try again. To unload an a loaded AppleScript
type "/unload scriptname".
Snak implements a number of event handlers that enable you to implement extensive
functionality and the number of handlers will be improved in the next version.
I welcome your feedback and suggestions so be sure to let me know if you need
a particular feature.
Event handlers
The real power of the AppleScript support comes into play when you wish to modify
how Snak does particular things.
Example: If you are an IRC server operator you will get a number of messages from
the network itself about the various going ons. This may become annoying if the
messages are of no relevance to you.
With AppleScript you now have a way to intercept those messages and process or
discard them without cluttering up the channels you are in.
Snak will, during its processing of the numerous different events, call some user-defined
"hook functions" or event handlers. Depending on the output of these
event handlers, Snak may or may not continue processing the event. This means
that the user now has the ability to tailor Snak much more closely to his or her
needs than ever before.
Snak comes with the script file SnakEventHandlers which contains examples of all
the event handlers that Snak currently supports, and shows what parameters they
require.
The following example employs an event handler called "on servernotice".
Snak will call the servernotice handler whenever it receives a notice from a server
as opposed to a normal user. The example script will then examine the text of
the notice and if it contains the string [CLONES] the message will be redirected
to a custom window in order not to clutter up the regular channel.
Notice how the return value of the handler in the case of a [CLONES] message is
true. This means that the script has completely processed the event and Snak should
not process it as well.
on servernotice(con, source, sourcehost, target, thestring)
set eventhandled to false
tell application "Snak 4.7" tryif thestring contains "clones" thentell connection con
echo thestring in filter "[CLONES]" end tell-- true tells Snak that this event is completely handledset eventhandled to true
end ifend tryend tellreturn eventhandled
end servernotice
on load()
tell application "Snak 4.7" set con to currentconnection
tell connection con
type "/window new name [CLONES]" echo "Clone catcher" in filter "[CLONES]" end tellend tellend load
The script uses the custom windows feature of Snak. The line "type "/window
new name [CLONES]" will open a custom window that you can use to display
text that is filtered out of somewhere else. Such windows are called filter windows.
Stacked event handlers
Snak allows you to have multiple AppleScripts loaded and each of the scripts can
implement whatever event handlers it wants. Snak will then call each event handler
in turn until one of them returns true, meaning that the event was completely
processed.
Snak comes with some sample event handler scripts that illustrate this. If you
examine the input1 and input2 scripts in the script folder you will see that they
both have an on input handler. If you load them with "/load input1"
and "/load input2" and type the text that triggers the action, you will
see that both handlers are called.
Likewise, idle handlers can be stacked. The idle1 and idle2 scripts both contain
idle handlers and if you load them with "/load idle1" and "/load
idle2" you will see periodic messages coming from both of them.
This support for stacked handlers will eliminate much complexity from large script
packages.